// File: jmcomic-core/src/main/java/dev/jukomu/common/base/packer/PackerUtils.java
package dev.jukomu.common.base.packer;

import dev.jukomu.common.util.file.FileUtils;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

/**
 * Packer的实用工具类，用于根据文件类型获取对应的Packer。
 */
public class PackerUtils {

    public static final String MODE_YML = "yml";
    public static final String MODE_JSON = "json";
    // public static final String MODE_PY_PICKLE = "pickle"; // 不支持Python Pickle

    private static final Map<String, Class<? extends Packer>> MODE_MAPPING = new HashMap<>();

    static {
        MODE_MAPPING.put(MODE_YML, YamlPacker.class);
        MODE_MAPPING.put(MODE_JSON, JsonPacker.class);
        // MODE_MAPPING.put(MODE_PY_PICKLE, PicklePacker.class); // 不添加PicklePacker
    }

    /**
     * 根据模式字符串获取Packer实例。
     *
     * @param mode 模式字符串（"yml", "json"）
     * @return Packer实例
     * @throws IllegalArgumentException 如果模式未知
     */
    public static Packer getPacker(String mode) {
        Class<? extends Packer> packerClass = MODE_MAPPING.get(mode);
        if (packerClass == null) {
            throw new IllegalArgumentException(
                    "Unknown mode: '" + mode + "', acceptable modes=" + MODE_MAPPING.keySet()
            );
        }
        try {
            return packerClass.getDeclaredConstructor().newInstance(); // 创建Packer实例
        } catch (InstantiationException | IllegalAccessException | NoSuchMethodException |
                 InvocationTargetException e) {
            throw new RuntimeException("Failed to create Packer instance for mode: " + mode, e);
        }
    }

    /**
     * 根据文件路径后缀决定使用哪个Packer。
     *
     * @param filepath 文件路径
     * @return 对应的Packer实例
     */
    public static Packer decidePacker(String filepath) {
        String suffix = FileUtils.getFileSuffix(filepath, true); // 获取不带点的后缀
        return getPacker(suffix.toLowerCase()); // 转换为小写匹配模式
    }

    /**
     * 将对象序列化到文件。
     *
     * @param obj      要序列化的对象
     * @param filepath 文件路径
     * @throws IOException 如果序列化失败
     */
    public static void pack(Object obj, String filepath) throws IOException {
        Packer packer = decidePacker(filepath);
        packer.pack(obj, filepath);
    }

    /**
     * 从文件反序列化对象。
     *
     * @param filepath 文件路径
     * @param clazz    预期反序列化的目标类型（可选）
     * @param <T>      目标类型
     * @return 反序列化后的对象
     * @throws IOException            如果反序列化失败
     * @throws ClassNotFoundException 如果找不到目标类
     */
    public static <T> T unpack(String filepath, Class<T> clazz) throws IOException, ClassNotFoundException {
        Packer packer = decidePacker(filepath);
        return packer.unpack(filepath, clazz);
    }

    /**
     * 从文件反序列化对象，不指定目标类型（通常解析为Map或List）。
     *
     * @param filepath 文件路径
     * @return 反序列化后的对象（通常为Map或List）
     * @throws IOException            如果反序列化失败
     * @throws ClassNotFoundException 如果找不到目标类
     */
    public static Object unpack(String filepath) throws IOException, ClassNotFoundException {
        return unpack(filepath, null);
    }

    /**
     * 从字符串反序列化对象。
     *
     * @param text  要反序列化的字符串
     * @param mode  模式字符串（"yml", "json"）
     * @param clazz 预期反序列化的目标类型（可选）
     * @param <T>   目标类型
     * @return 反序列化后的对象
     * @throws IOException 如果反序列化失败
     */
    public static <T> T unpackByString(String text, String mode, Class<T> clazz) throws IOException {
        Packer packer = getPacker(mode);
        return packer.unpackByString(text, clazz);
    }

    /**
     * 从字符串反序列化对象，不指定目标类型。
     *
     * @param text 要反序列化的字符串
     * @param mode 模式字符串（"yml", "json"）
     * @return 反序列化后的对象（通常为Map或List）
     * @throws IOException 如果反序列化失败
     */
    public static Object unpackByString(String text, String mode) throws IOException {
        return unpackByString(text, mode, null);
    }
}